<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="theme-color" content="#0078E7"><meta name="author" content="CC康纳百川"><meta name="copyright" content="CC康纳百川"><meta name="generator" content="Hexo 5.2.0"><meta name="theme" content="hexo-theme-yun"><title>基于小波变换的数字水印检测 | CC康纳百川</title><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@900&amp;display=swap" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/star-markdown-css@0.1.21/dist/yun/yun-markdown.min.css"><script src="//at.alicdn.com/t/font_1140697_ed8vp4atwoj.js" async></script><script src="https://cdn.jsdelivr.net/npm/scrollreveal/dist/scrollreveal.min.js" defer></script><script>document.addEventListener("DOMContentLoaded", () => {
  [".post-card",".post-content img"].forEach((target)=> {
    ScrollReveal().reveal(target);
  })
});
</script><link rel="shortcut icon" type="image/svg+xml" href="/yun/yun.svg"><link rel="mask-icon" href="/yun/yun.svg" color="#0078E7"><link rel="alternate icon" href="/yun.ico"><link rel="preload" href="/yun/css/hexo-theme-yun.css" as="style"><link rel="preload" href="/yun/js/utils.js" as="script"><link rel="preload" href="/yun/js/hexo-theme-yun.js" as="script"><link rel="prefetch" href="/yun/js/sidebar.js" as="script"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><link rel="stylesheet" href="/yun/css/hexo-theme-yun.css"><script id="yun-config">
    const Yun = window.Yun || {};
    window.CONFIG = {"hostname":"ccknbc.github.io","root":"/yun/","title":"云游君的小站","version":"1.2.0","mode":"time","copycode":true,"anonymous_image":"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg","say":{"api":"https://v1.hitokoto.cn","hitokoto":true},"local_search":{"path":"/yun/search.xml"},"fireworks":{"colors":["102, 167, 221","62, 131, 225","33, 78, 194"]}};
  </script><script>(function(){
  var bp = document.createElement('script');
  var curProtocol = window.location.protocol.split(':')[0];
  if (curProtocol === 'https') {
    bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
  }
  else {
    bp.src = 'http://push.zhanzhang.baidu.com/push.js';
  }
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(bp, s);
})();</script><meta name="description" content="数字水印技术原理 数字水印技术实际上就是通过对水印载体的分析、水印信息的处理、水印嵌入点的选择、嵌入方式的设计、嵌入调制的控制和提取检测方法等相关技术环节进行合理优化，寻求满足不可感知性、鲁棒性和安全性等约束条件下的准最优化设计问题。在实际应用中，一个完整水印系统的设计通常包括水印的生成、嵌入、检测和提取四个部分。 1  水印生成 通常基于伪随机数发生器或混沌系统来产生水印信号，从水印的鲁棒性和安">
<meta property="og:type" content="article">
<meta property="og:title" content="基于小波变换的数字水印检测">
<meta property="og:url" content="https://ccknbc.github.io/yun/posts/1/">
<meta property="og:site_name" content="CC康纳百川">
<meta property="og:description" content="数字水印技术原理 数字水印技术实际上就是通过对水印载体的分析、水印信息的处理、水印嵌入点的选择、嵌入方式的设计、嵌入调制的控制和提取检测方法等相关技术环节进行合理优化，寻求满足不可感知性、鲁棒性和安全性等约束条件下的准最优化设计问题。在实际应用中，一个完整水印系统的设计通常包括水印的生成、嵌入、检测和提取四个部分。 1  水印生成 通常基于伪随机数发生器或混沌系统来产生水印信号，从水印的鲁棒性和安">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfsmLi.gif">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfsGAW.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfs4wL.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfsHFw.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfschv.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfs5JR.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfsAjg.png">
<meta property="og:image" content="https://t1.picb.cc/uploads/2020/06/09/tfs848.png">
<meta property="article:published_time" content="2020-06-09T12:52:00.000Z">
<meta property="article:modified_time" content="2020-06-09T13:00:00.000Z">
<meta property="article:author" content="CC康纳百川">
<meta property="article:tag" content="study">
<meta property="article:tag" content="watermark">
<meta property="article:tag" content="matlab">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://t1.picb.cc/uploads/2020/06/09/tfsmLi.gif"><script src="/yun/js/ui/mode.js"></script></head><body><script defer src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script defer src="/yun/js/ui/fireworks.js"></script><canvas class="fireworks"></canvas><div class="container"><a class="sidebar-toggle hty-icon-button" id="menu-btn"><div class="hamburger hamburger--spin" type="button"><span class="hamburger-box"><span class="hamburger-inner"></span></span></div></a><div class="sidebar-toggle sidebar-overlay"></div><aside class="sidebar"><script src="/yun/js/sidebar.js"></script><ul class="sidebar-nav"><li class="sidebar-nav-item sidebar-nav-toc hty-icon-button" data-target="post-toc-wrap" title="文章目录"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-list-ordered"></use></svg></li><li class="sidebar-nav-item sidebar-nav-overview hty-icon-button sidebar-nav-active" data-target="site-overview-wrap" title="站点概览"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-passport-line"></use></svg></li></ul><div class="sidebar-panel sidebar-panel-active" id="site-overview-wrap"><div class="site-info mickey-mouse"><a class="site-author-avatar" href="/yun/about/" title="CC康纳百川"><img width="96" loading="lazy" src="/yun/Yun.png" alt="CC康纳百川"><span class="site-author-status" title="永远相信美好的事情即将发生">😊</span></a><div class="site-author-name"><a href="/yun/about/">CC康纳百川</a></div><a class="site-name" href="/yun/about/site">CC康纳百川</a><sub class="site-subtitle">Hello Word</sub><div class="site-desciption">一个无趣的人</div></div><nav class="site-state"><a class="site-state-item hty-icon-button icon-home" href="/yun/" title="首页"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-home-4-line"></use></svg></span></a><div class="site-state-item"><a href="/yun/archives/" title="归档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-archive-line"></use></svg></span><span class="site-state-item-count">10</span></a></div><div class="site-state-item"><a href="/yun/categories/" title="分类"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-2-line"></use></svg></span><span class="site-state-item-count">16</span></a></div><div class="site-state-item"><a href="/yun/tags/" title="标签"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="site-state-item-count">18</span></a></div><a class="site-state-item hty-icon-button" target="_blank" rel="noopener" href="https://yun.yunyoujun.cn" title="文档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-settings-line"></use></svg></span></a></nav><hr style="margin-bottom:0.5rem"><div class="links-of-author"><a class="links-of-author-item hty-icon-button" rel="noopener" href="/atom.xml" title="RSS" target="_blank" style="color:orange"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-rss-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://shang.qq.com/wpa/qunwpa?idkey=c929e704022704d8cced9ec355d44a3fa7ad34aea12cef1de03d75d3d7d5b059" title="QQ 群" target="_blank" style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://github.com/YunYouJun" title="GitHub" target="_blank" style="color:#6e5494"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-github-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://weibo.com/jizhideyunyoujun" title="微博" target="_blank" style="color:#E6162D"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-weibo-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://www.douban.com/people/yunyoujun/" title="豆瓣" target="_blank" style="color:#007722"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-douban-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://music.163.com/#/user/home?id=247102977" title="网易云音乐" target="_blank" style="color:#C20C0C"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-netease-cloud-music-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://www.zhihu.com/people/yunyoujun/" title="知乎" target="_blank" style="color:#0084FF"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-zhihu-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://space.bilibili.com/1579790" title="哔哩哔哩" target="_blank" style="color:#FF8EB3"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-bilibili-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://twitter.com/YunYouJun" title="Twitter" target="_blank" style="color:#1da1f2"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-twitter-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://t.me/elpsycn" title="Telegram Channel" target="_blank" style="color:#0088CC"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-telegram-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="mailto:me@yunyoujun.cn" title="E-Mail" target="_blank" style="color:#8E71C1"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-mail-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://travellings.now.sh/" title="Travelling" target="_blank" style="color:var(--hty-text-color)"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-send-plane-2-line"></use></svg></a></div><hr style="margin:0.5rem 1rem"><div class="links"><a class="links-item hty-icon-button" href="/yun/links/" title="我的小伙伴们" style="color:dodgerblue"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-genderless-line"></use></svg></a></div><br><a class="links-item hty-icon-button" id="toggle-mode-btn" href="javascript:;" title="Mode" style="color: #f1cb64"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-contrast-2-line"></use></svg></a></div><div class="sidebar-panel" id="post-toc-wrap"><div class="post-toc"><div class="post-toc-content">此文章未包含目录</div></div></div></aside><main class="sidebar-translate" id="content"><div id="post"><article class="post-block" itemscope itemtype="https://schema.org/Article"><link itemprop="mainEntityOfPage" href="https://ccknbc.github.io/yun/yun/posts/1/"><span hidden itemprop="author" itemscope itemtype="https://schema.org/Person"><meta itemprop="name" content="CC康纳百川"><meta itemprop="description"></span><span hidden itemprop="publisher" itemscope itemtype="https://schema.org/Organization"><meta itemprop="name" content="CC康纳百川"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">基于小波变换的数字水印检测<a class="post-edit-link" href="https://github.com/ccknbc-actions/blog-yun/blob/master/source/_posts/学习/数字水印的嵌入与提取.md" target="_blank" title="编辑" rel="noopener"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-edit-line"></use></svg></a></h1><div class="post-meta"><div class="post-time" style="display:block"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-line"></use></svg></span> <span class="post-meta-icon-text">发表于</span> <time title="创建时间：2020-06-09 20:52:00" itemprop="dateCreated datePublished" datetime="2020-06-09T20:52:00+08:00">2020-06-09</time></div><span class="post-count"><span class="post-symbolcount"><span class="post-meta-item-icon" title="本文字数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-file-word-line"></use></svg></span> <span title="本文字数">3k</span><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读时长"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-timer-line"></use></svg></span> <span title="阅读时长">12m</span></span></span><span class="post-busuanzi"><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读次数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg> <span id="busuanzi_value_page_pv"></span></span></span><div class="post-classify"><span class="post-category"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-line"></use></svg></span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a class="category" href="/yun/categories/%E5%AD%A6%E4%B9%A0/" style="--text-color:var(--hty-text-color)" itemprop="url" rel="index"><span itemprop="text">学习</span></a></span> > <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a class="category" href="/yun/categories/%E5%AD%A6%E4%B9%A0/matlab/" style="--text-color:var(--hty-text-color)" itemprop="url" rel="index"><span itemprop="text">matlab</span></a></span></span><span class="post-tag"><span class="post-meta-divider">-</span><a class="tag" href="/yun/tags/study/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">study</span></a><a class="tag" href="/yun/tags/watermark/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">watermark</span></a><a class="tag" href="/yun/tags/matlab/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">matlab</span></a></span></div><div class="post-author"><div class="author-avatar"><img src="https://www.gravatar.com/avatar/1928aaddbe6e7107395bf3ac99f35886?s=20&amp;d=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2FYunYouJun%2Fcdn%2Fimg%2Favatar%2Fnone.jpg"></div><span class="author-name">CC</span></div></div></header><section class="post-body" itemprop="articleBody"><div class="post-content markdown-body" style="--smc-primary:#0078E7;"><p><strong>数字水印技术原理</strong></p>
<p>数字水印技术实际上就是通过对水印载体的分析、水印信息的处理、水印嵌入点的选择、嵌入方式的设计、嵌入调制的控制和提取检测方法等相关技术环节进行合理优化，寻求满足不可感知性、鲁棒性和安全性等约束条件下的准最优化设计问题。在实际应用中，一个完整水印系统的设计通常包括水印的生成、嵌入、检测和提取四个部分。</p>
<p><strong>1  水印生成</strong></p>
<p>通常基于伪随机数发生器或混沌系统来产生水印信号，从水印的鲁棒性和安全性方面来考虑，常常需要对原水印进行预处理来适应水印嵌入贺认。</p>
<p><strong>2</strong> <strong>水印嵌入</strong></p>
<p>在尽量保证水印不可感知性的前提下，嵌入最大强度的水印，可提高水印的稳健性。常用的水印嵌入准则有加法准则、乘法准则和融合准则。</p>
<p><strong>3水印检测</strong></p>
<p>指判断水印载体中是否存在水印的过程。</p>
<p><strong>4水印提取</strong></p>
<p>指水印被比较精确地提取的过程。 水印的提取和检测可以需要原始图像的参与（明检测）， 也可不需要原始图像的参与（盲检测）</p>
<p><strong>数字水印的分类</strong></p>
<ul>
<li>按水印的特性</li>
<li>鲁棒数字水印：要求嵌入的水印能够经受各种常用的编辑处理</li>
<li>脆弱数字水印：需要对信号的改动足够敏感，是人们能够根据脆弱水印的状态判断出数据是否被篡改。</li>
<li>按水印的检测过程</li>
<li>明文水印：检测工程中，需要原始数据。普遍来讲，鲁棒性较之盲水印要好。</li>
<li>盲水印：只需要密钥，不需要原始数据</li>
<li>按水印的内容</li>
<li>有意义水印：水印是商标、音频片段等</li>
<li>无意义水印：序列号，仅检测是否含水印</li>
<li>按水印的隐藏位置</li>
<li>空域</li>
<li>频域</li>
<li>时域</li>
</ul>
<p>数字水印技术基本上具有下面几个方面的特点：</p>
<p>—-<strong>安全性</strong>：数字水印的信息应是安全的，难以篡改或伪造，同时，应当有较低的误检测率，当原内容发生变化时，数字水印应当发生变化，从而可以检测原始数据的变更；当然数字水印同样对重复添加有很强的抵抗性</p>
<p>—-<strong>隐蔽性</strong>：数字水印应是不可知觉的，而且应不影响被保护数据的正常使用；不会降质；</p>
<p>—-<strong>鲁棒性</strong>：是指在经历多种无意或有意的信号处理过程后，数字水印仍能保持部分完整性并能被准确鉴别。可能的信号处理过程包括信道噪声、滤波、数/模与模/数转换、重采样、剪切、位移、尺度变化以及有损压缩编码等。</p>
<p>–<strong>嵌入容量</strong>(embedding capacity)：是指载体在不发生形变的前提下可嵌入的水印信息量。尤其是隐蔽通信领域的特殊性，对水印的容量需求很大。</p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfsmLi.gif" alt="tfsmLi.gif" loading="lazy" loading="lazy"></p>
<p><strong>图1 数字水印嵌入与提取框图</strong></p>
<p><strong>典型的数字水印算法</strong></p>
<p><strong>数字水印的技术实现</strong></p>
<p><strong>空域-LSB</strong></p>
<p>LSB方法是最简单的嵌入水印的方法。事实上 ，任何一幅 图片都具备一定的容噪性 ，这表现在像素数据的最低有效位(Least Significant Bit，LSB)对 人 眼的视觉影响很 小，秘密信息就隐藏在图像每一个像素的最低位或次低位 ，实现其不 可见性。</p>
<p><strong>频域</strong></p>
<p>将图片的灰度强弱，视为图片的频域。通过某种变换手段（傅里叶变换，离散余弦变换，小波变换等）将图像变换到频域（小波域），在频域对图像添加水印，再通过逆变换，将图像转换为空间域。相对于空域手段，频域手段隐匿性更强，抗攻击性更高。</p>
<p><strong>DCT</strong></p>
<p>DCT以8x8的像素为单位进行，生成的是8x8的DCT系数数据块。DCT变换的最大特点是对于一般的图像都能够将像块的能量集中于少数低频DCT系数上，即生成8x8DCT系数块中，仅左上角的少量低频系数数值较大，其余系数的数值很小，这样就可能只编码和传输少数系数而不严重影响图像质量。</p>
<p><strong>小波变换</strong></p>
<p>“小波”就是小区域、长度有限、均值为0的波形。小波变换就是选择适当的基本小波或母小波ψ(t)，通过对基本小波的平移、伸缩而形成一系列的小波，这簇小波作为基可以构成一系列嵌套的（信号）子空间，然后将欲分析的信号（例如图像）投影到各个大小不同的（信号）子空间之中，以观察相应的特性。这样，就相当于我们用不同的焦距去观察一个物体，可从宏观到微观，从概貌到细节观察得十分详尽。所以小波变换又被称为“数学显微镜”。</p>
<p><strong>空域+频域</strong></p>
<p>该算法通过混沌置乱水印图像，建立水印与载体数据之间的Hash单向映射函数，使用两种不同的嵌入方法，先后嵌入水印到空域和DFT域。水印被多次嵌入，实现了水印的盲提取。</p>
<p><strong>数字水印的应用场景</strong></p>
<ul>
<li>多媒体作品盗版追溯：利用数字水印的不可见性，在不影响作品的情况下，加入版权信息的数字水印，可抗击拷贝，剪切。</li>
<li>证件的防伪认证：如学历证，合同，票据等，携带数字水印后，可通过制定的方式提取水印，验证证件等数字文件是否被涂改；</li>
<li>阿里事件：阿里追查泄密员工的时间本身，说明，水印可以有效的追溯信息的释放源；</li>
<li>隐蔽信息传递：水印可携带加密信息后，藏在多媒体文件中传播，并通过特定的提取方式获取水印。可以作为一种隐蔽信息的通信方式。</li>
</ul>
<p><strong>源程序代码及部分注释</strong> </p>
<p><strong>基础设置模块，同时存储着密钥，全局变量 main.m</strong></p>
<figure class="highlight matlab"><table><tr><td class="code"><pre><span class="line"><span class="keyword">global</span> I ;</span><br><span class="line"><span class="keyword">global</span> W;</span><br><span class="line"><span class="keyword">global</span> P;</span><br><span class="line"><span class="keyword">global</span> Iw;</span><br><span class="line">ntimes=<span class="number">23</span>; <span class="comment">% 秘钥1,Arnold置乱次数</span></span><br><span class="line">rngseed=<span class="number">59433</span>; <span class="comment">% 秘钥2，随机数种子</span></span><br><span class="line">flag=<span class="number">1</span>; <span class="comment">%是否显示图像，0 不显示，1 显示</span></span><br></pre></td></tr></table></figure>

<p> <strong>嵌入水印模块：setdwtwatermark.m</strong></p>
<figure class="highlight matlab"><table><tr><td class="code"><pre><span class="line">matlabfunction [Iw,psnr]=setdwtwatermark(I,W,ntimes,rngseed,flag)</span><br><span class="line"><span class="comment">%基于小波变换数字水印嵌入</span></span><br><span class="line"><span class="comment">%I：载体图像，灰度图</span></span><br><span class="line"><span class="comment">%W：水印图像，二值图，且长宽相等</span></span><br><span class="line"><span class="comment">%ntimes: 秘钥1,Arnold置乱次数</span></span><br><span class="line">I=imcrop(I,[<span class="number">0</span> <span class="number">0</span> <span class="built_in">size</span>(I,<span class="number">2</span>) <span class="built_in">size</span>(I,<span class="number">1</span>)<span class="number">-1</span>]);</span><br><span class="line"><span class="built_in">type</span>=class(I);</span><br><span class="line">I=double(I);</span><br><span class="line">W=logical(W);</span><br><span class="line">[mI,nI]=<span class="built_in">size</span>(I);</span><br><span class="line">[mW,nW]=<span class="built_in">size</span>(W);</span><br><span class="line"><span class="keyword">if</span> mW~=nW</span><br><span class="line">  error(<span class="string">&#x27;SETDWTWATERMARK:ARNOLD&#x27;</span>,<span class="string">&#x27;ARNOLD置乱要求水印图像长宽必须相等！&#x27;</span>)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">[ca1,ch1,cv1,cd1]=dwt2(I,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line">[ca2,ch2,cv2,cd2]=dwt2(ca1,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line"><span class="keyword">if</span> flag</span><br><span class="line">  <span class="built_in">figure</span>(<span class="string">&#x27;Name&#x27;</span>,<span class="string">&#x27;载体小波分解&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">121</span>)</span><br><span class="line">  imagesc([wcodemat(ca1),wcodemat(ch1);wcodemat(cv1),wcodemat(cd1)])</span><br><span class="line">  title(<span class="string">&#x27;一级小波分解&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">122</span>)</span><br><span class="line">  imagesc([wcodemat(ca2),wcodemat(ch2);wcodemat(cv2),wcodemat(cd2)])</span><br><span class="line">  title(<span class="string">&#x27;二级小波分解&#x27;</span>)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">Wa=W;</span><br><span class="line">H=[<span class="number">1</span>,<span class="number">1</span>;<span class="number">1</span>,<span class="number">2</span>]^ntimes; </span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span>=<span class="number">1</span>:nW</span><br><span class="line">  <span class="keyword">for</span> <span class="built_in">j</span>=<span class="number">1</span>:nW</span><br><span class="line">​    idx=<span class="built_in">mod</span>(H*[<span class="built_in">i</span><span class="number">-1</span>;<span class="built_in">j</span><span class="number">-1</span>],nW)+<span class="number">1</span>;</span><br><span class="line">​    Wa(idx(<span class="number">1</span>),idx(<span class="number">2</span>))=W(<span class="built_in">i</span>,<span class="built_in">j</span>);</span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span> </span><br><span class="line">flag=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> flag</span><br><span class="line">  <span class="built_in">figure</span>(<span class="string">&#x27;Name&#x27;</span>,<span class="string">&#x27;水印置乱与嵌入&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">221</span>)</span><br><span class="line">  imshow(W)</span><br><span class="line">  title(<span class="string">&#x27;原始水印&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">222</span>)</span><br><span class="line">  imshow(Wa)</span><br><span class="line">  title([<span class="string">&#x27;置乱水印，变换次数=&#x27;</span>,num2str(ntimes)]);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="comment">%数字水印嵌入</span></span><br><span class="line">ca2w=ca2;</span><br><span class="line">rng(rngseed);</span><br><span class="line">idx=randperm(<span class="built_in">numel</span>(ca2),<span class="built_in">numel</span>(Wa));</span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span>=<span class="number">1</span>:<span class="built_in">numel</span>(Wa)</span><br><span class="line">  c=ca2(idx(<span class="built_in">i</span>));</span><br><span class="line">  z=<span class="built_in">mod</span>(c,nW);</span><br><span class="line">  <span class="keyword">if</span> Wa(<span class="built_in">i</span>)</span><br><span class="line">​    <span class="keyword">if</span> z&lt;nW/<span class="number">4</span></span><br><span class="line">​      f=c-nW/<span class="number">4</span>-z;</span><br><span class="line">​    <span class="keyword">else</span></span><br><span class="line">​      f=c+nW*<span class="number">3</span>/<span class="number">4</span>-z;</span><br><span class="line">​    <span class="keyword">end</span></span><br><span class="line">  <span class="keyword">else</span> </span><br><span class="line">​    <span class="keyword">if</span> z&lt;nW*<span class="number">3</span>/<span class="number">4</span></span><br><span class="line">​      f=c+nW/<span class="number">4</span>-z;</span><br><span class="line">​    <span class="keyword">else</span></span><br><span class="line">​      f=c+nW*<span class="number">5</span>/<span class="number">4</span>-z;</span><br><span class="line">​    <span class="keyword">end</span></span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line">  ca2w(idx(<span class="built_in">i</span>))=f;</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">ca1w=idwt2(ca2w,ch2,cv2,cd2,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line">Iw=idwt2(ca1w,ch1,cv1,cd1,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line">Iw=Iw(<span class="number">1</span>:mI,<span class="number">1</span>:nI);</span><br><span class="line">mn=<span class="built_in">numel</span>(I);</span><br><span class="line">Imax=<span class="built_in">max</span>(I(:));</span><br><span class="line">psnr=<span class="number">10</span>*<span class="built_in">log10</span>(mn*Imax^<span class="number">2</span>/sum((I(:)-Iw(:)).^<span class="number">2</span>));</span><br><span class="line">I=cast(I,<span class="built_in">type</span>);</span><br><span class="line">Iw=cast(Iw,<span class="built_in">type</span>);</span><br><span class="line"><span class="keyword">if</span> flag</span><br><span class="line">  subplot(<span class="number">223</span>)</span><br><span class="line">  imshow(I);</span><br><span class="line">  title(<span class="string">&#x27;原始图像&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">224</span>);</span><br><span class="line">  imshow(Iw);</span><br><span class="line">  title([<span class="string">&#x27;添加水印，PSNR=&#x27;</span>,num2str(psnr)]);</span><br><span class="line"><span class="keyword">end</span> </span><br></pre></td></tr></table></figure>

<p><strong>提取水印模块：getdwtwatermark.m</strong></p>
<figure class="highlight matlab"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="params">[Wg,nc]</span>=<span class="title">getdwtwatermark</span><span class="params">(Iw,W,P,ntimes,rngseed,flag)</span></span></span><br><span class="line">[mW,nW]=<span class="built_in">size</span>(W);</span><br><span class="line"><span class="keyword">if</span> mW~=nW</span><br><span class="line">  error(<span class="string">&#x27;GETDWTWATERMARK:ARNOLD&#x27;</span>,<span class="string">&#x27;ARNOLD置乱要求水印图像长宽必须相等！&#x27;</span>)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">Iw=double(Iw);</span><br><span class="line">W=logical(W);</span><br><span class="line">ca1w=dwt2(Iw,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line">ca2w=dwt2(ca1w,<span class="string">&#x27;haar&#x27;</span>);</span><br><span class="line">Wa=W;</span><br><span class="line">rng(rngseed);</span><br><span class="line">idx=randperm(<span class="built_in">numel</span>(ca2w),<span class="built_in">numel</span>(Wa));</span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span>=<span class="number">1</span>:<span class="built_in">numel</span>(Wa)</span><br><span class="line">  c=ca2w(idx(<span class="built_in">i</span>));</span><br><span class="line">  z=<span class="built_in">mod</span>(c,nW);</span><br><span class="line">  <span class="keyword">if</span> z&lt;nW/<span class="number">2</span></span><br><span class="line">​    Wa(<span class="built_in">i</span>)=<span class="number">0</span>;</span><br><span class="line">  <span class="keyword">else</span></span><br><span class="line">​    Wa(<span class="built_in">i</span>)=<span class="number">1</span>;</span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">Wg=Wa;</span><br><span class="line">H=[<span class="number">2</span> <span class="number">-1</span>;<span class="number">-1</span>,<span class="number">1</span>]^ntimes;</span><br><span class="line"><span class="keyword">for</span> <span class="built_in">i</span>=<span class="number">1</span>:nW</span><br><span class="line">  <span class="keyword">for</span> <span class="built_in">j</span>=<span class="number">1</span>:nW</span><br><span class="line">​    idx=<span class="built_in">mod</span>(H*[<span class="built_in">i</span><span class="number">-1</span>;<span class="built_in">j</span><span class="number">-1</span>],nW)+<span class="number">1</span>;</span><br><span class="line">​    Wg(idx(<span class="number">1</span>),idx(<span class="number">2</span>))=Wa(<span class="built_in">i</span>,<span class="built_in">j</span>);</span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">nc=sum(Wg(:).*W(:))/<span class="built_in">sqrt</span>(sum(Wg(:).^<span class="number">2</span>))/<span class="built_in">sqrt</span>(sum(W(:).^<span class="number">2</span>));</span><br><span class="line">flag=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> flag</span><br><span class="line">  <span class="built_in">figure</span>(<span class="string">&#x27;Name&#x27;</span>,<span class="string">&#x27;数字水印提取结果&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">121</span>)</span><br><span class="line">  W=imcrop(W,[<span class="number">0</span> <span class="number">0</span> <span class="built_in">size</span>(P,<span class="number">2</span>) <span class="built_in">size</span>(P,<span class="number">1</span>)]);  </span><br><span class="line"> imshow(W)</span><br><span class="line">  title(<span class="string">&#x27;原始水印&#x27;</span>)</span><br><span class="line">  subplot(<span class="number">122</span>)</span><br><span class="line">  Wg=imcrop(Wg,[<span class="number">0</span> <span class="number">0</span> <span class="number">122</span> <span class="number">107</span>]);</span><br><span class="line">  imshow(Wg)</span><br><span class="line">  title([<span class="string">&#x27;提取水印，NC=&#x27;</span>,num2str(nc)]);</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>

<p><strong>GUI调用模块 watermatk.m</strong></p>
<figure class="highlight matlab"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">varargout</span> = <span class="title">watermark</span><span class="params">(varargin)</span></span></span><br><span class="line">gui_Singleton = <span class="number">1</span>;</span><br><span class="line">gui_State = struct(<span class="string">&#x27;gui_Name&#x27;</span>,    mfilename, ...</span><br><span class="line">​          <span class="string">&#x27;gui_Singleton&#x27;</span>, gui_Singleton, ...</span><br><span class="line">​          <span class="string">&#x27;gui_OpeningFcn&#x27;</span>, @watermark_OpeningFcn, ...</span><br><span class="line">​          <span class="string">&#x27;gui_OutputFcn&#x27;</span>, @watermark_OutputFcn, ...</span><br><span class="line">​          <span class="string">&#x27;gui_LayoutFcn&#x27;</span>, [] , ...</span><br><span class="line">​          <span class="string">&#x27;gui_Callback&#x27;</span>,  []);</span><br><span class="line"><span class="keyword">if</span> nargin &amp;&amp; ischar(varargin&#123;<span class="number">1</span>&#125;)</span><br><span class="line">  gui_State.gui_Callback = str2func(varargin&#123;<span class="number">1</span>&#125;);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">if</span> nargout</span><br><span class="line">  [varargout&#123;<span class="number">1</span>:nargout&#125;] = gui_mainfcn(gui_State, varargin&#123;:&#125;);</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">  gui_mainfcn(gui_State, varargin&#123;:&#125;);</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">watermark_OpeningFcn</span><span class="params">(hObject, eventdata, handles, varargin)</span></span></span><br><span class="line">movegui( hObject,<span class="string">&#x27;center&#x27;</span> );</span><br><span class="line">handles.output = hObject;<span class="comment">%移动窗口到屏幕中心</span></span><br><span class="line">guidata(hObject, handles);</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">varargout</span> = <span class="title">watermark_OutputFcn</span><span class="params">(hObject, eventdata, handles)</span> </span></span><br><span class="line">varargout&#123;<span class="number">1</span>&#125; = handles.output </span><br><span class="line"><span class="comment">% --- Executes on button press in pushbutton1.</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">pushbutton1_Callback</span><span class="params">(hObject, eventdata, handles)</span> </span></span><br><span class="line">main</span><br><span class="line">[filename pathname]=uigetfile(&#123;<span class="string">&#x27;*.jpg;*.bmp&#x27;</span>;<span class="string">&#x27;*.*&#x27;</span>&#125;,<span class="string">&#x27;请选择底图文件&#x27;</span>);</span><br><span class="line"><span class="comment">%%打开图像</span></span><br><span class="line">I=imread(filename); <span class="comment">%读取原始图像</span></span><br><span class="line">[filename pathname]=uigetfile(&#123;<span class="string">&#x27;*.png;*.tif&#x27;</span>;<span class="string">&#x27;*.*&#x27;</span>&#125;,<span class="string">&#x27;请选择水印文件&#x27;</span>);</span><br><span class="line">helpdlg(<span class="string">&#x27;选择完毕，您可点击查看以确认是否需要重新选择&#x27;</span>,<span class="string">&#x27;提示&#x27;</span>);</span><br><span class="line">I = rgb2gray(I);<span class="comment">%转换为灰度图</span></span><br><span class="line">W = imread(filename);<span class="comment">%读取水印图像</span></span><br><span class="line"><span class="keyword">if</span> strcmp(filename(<span class="keyword">end</span><span class="number">-3</span>:<span class="keyword">end</span>),<span class="string">&#x27;tif&#x27;</span>)</span><br><span class="line">  W= rgb2gray(W);</span><br><span class="line">  W=imbinarize(W);<span class="comment">%转化成二值图像</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">P=W;</span><br><span class="line">Mm=<span class="built_in">size</span>(W,<span class="number">1</span>); <span class="comment">%水印的行数</span></span><br><span class="line">Nm=<span class="built_in">size</span>(W,<span class="number">2</span>); <span class="comment">%水印的列数</span></span><br><span class="line"><span class="comment">%将图像扩展为长宽相等</span></span><br><span class="line"><span class="keyword">if</span> Mm&lt;Nm</span><br><span class="line">  Max=Nm;</span><br><span class="line">  Min=Mm;</span><br><span class="line">  <span class="keyword">for</span> <span class="built_in">i</span>=Min:Max</span><br><span class="line">​    <span class="keyword">for</span> <span class="built_in">j</span>=<span class="number">1</span>:Max</span><br><span class="line">​      W(<span class="built_in">i</span>,<span class="built_in">j</span>)=<span class="number">1</span>;</span><br><span class="line">​    <span class="keyword">end</span></span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">else</span> </span><br><span class="line">  Max=Mm;</span><br><span class="line">  Min=Nm;</span><br><span class="line">  <span class="keyword">for</span> <span class="built_in">i</span>=<span class="number">1</span>:Max</span><br><span class="line">​    <span class="keyword">for</span> <span class="built_in">j</span>=Min:Max</span><br><span class="line">​      W(<span class="built_in">i</span>,<span class="built_in">j</span>)=<span class="number">1</span>;</span><br><span class="line">​    <span class="keyword">end</span></span><br><span class="line">  <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span>  </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">pushbutton2_Callback</span><span class="params">(hObject, eventdata, handles)</span></span></span><br><span class="line">main</span><br><span class="line"><span class="built_in">figure</span>(<span class="string">&#x27;Name&#x27;</span>,<span class="string">&#x27;载体图像与水印图像&#x27;</span>)</span><br><span class="line">subplot(<span class="number">211</span>);</span><br><span class="line">imshow(I);</span><br><span class="line">title(<span class="string">&#x27;载体图像&#x27;</span>)</span><br><span class="line">subplot(<span class="number">212</span>);</span><br><span class="line">imshow(P);</span><br><span class="line">title(<span class="string">&#x27;水印图像&#x27;</span>) </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">pushbutton3_Callback</span><span class="params">(hObject, eventdata, handles)</span></span></span><br><span class="line">main</span><br><span class="line">[Iw,psnr]=setdwtwatermark(I,W,ntimes,rngseed,<span class="number">0</span>); </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">pushbutton4_Callback</span><span class="params">(hObject, eventdata, handles)</span></span></span><br><span class="line">main</span><br><span class="line">[Wg,nc]=getdwtwatermark(Iw,W,P,ntimes,rngseed,<span class="number">0</span>);</span><br></pre></td></tr></table></figure>

<p><strong>基于小波的水印技术 运行结果演示</strong></p>
<p><strong>1图像的选择与导入</strong></p>
<p>进入GUI主界面</p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfsGAW.png" alt="tfsGAW.png" loading="lazy" loading="lazy"></p>
<p><strong>图2 GUI主界面</strong></p>
<p>点击选择图片，分别选择载体图像和水印图像</p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfs4wL.png" alt="tfs4wL.png" loading="lazy" loading="lazy"></p>
<p><strong>图3 选择底图文件</strong></p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfsHFw.png" alt="tfsHFw.png" loading="lazy" loading="lazy"></p>
<p><strong>图4 选择水印文件</strong></p>
<p>两项都选择完毕后提示选择完成，</p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfschv.png" alt="tfschv.png" loading="lazy" loading="lazy"></p>
<p><strong>图5 选择完毕 帮助提示框</strong></p>
<p>对于取消选择未设置警告与报错提示，防止过多弹窗</p>
<p><strong>2载体图像小波变换</strong></p>
<p>这部分未单独新开按钮和图片显示窗口，但程序的确执行了，用户无需知晓</p>
<p><strong>3水印图像的预处理</strong></p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfs5JR.png" alt="tfs5JR.png" loading="lazy" loading="lazy"></p>
<p><strong>图6 预处理成二值图像后的水印</strong></p>
<p><strong>4小波数字水印的嵌入</strong></p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfsAjg.png" alt="tfsAjg.png" loading="lazy" loading="lazy"></p>
<p><strong>图7 原始水印和置乱水印以及原始图像和添加水印之后的图像对比</strong></p>
<p><strong>5小波数字水印的提取</strong></p>
<p><img src="https://t1.picb.cc/uploads/2020/06/09/tfs848.png" alt="tfs848.png" loading="lazy" loading="lazy"></p>
<p><strong>图8 原始水印和提取的水印的对比</strong></p>
<p>将原始水印和提取水印进行对比，两个相关系数为0.99356，相关系数越接近1, 则提取的水印和原始水印越相似。</p>
</div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者：</strong>CC</li><li class="post-copyright-link"><strong>本文链接：</strong><a href="https://ccknbc.github.io/yun/posts/1/" title="基于小波变换的数字水印检测">https://ccknbc.github.io/yun/posts/1/</a></li><li class="post-copyright-license"><strong>版权声明：</strong>本博客所有文章除特别声明外，均默认采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener" title="CC BY-NC-SA 4.0 "><svg class="icon"><use xlink:href="#icon-creative-commons-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-by-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-nc-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-sa-line"></use></svg></a> 许可协议。</li></ul><script>document.addEventListener('copy', function (event) {
  const clipboardData = event.clipboardData || window.clipboardData;
  if (!clipboardData) { return; }
  const text = window.getSelection().toString();
  if (text) {
    event.preventDefault();
    clipboardData.setData('text/plain', text + '\n\n本文作者：CC\n本文链接：https://ccknbc.github.io/yun/posts/1/\n版权声明：本博客所有文章除特别声明外，均默认采用 CC BY-NC-SA 4.0 许可协议。');
  }
});</script></section></article><div class="post-nav"><div class="post-nav-item"><a class="post-nav-prev" href="/yun/posts/2/" rel="prev" title="生产实习"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-left-s-line"></use></svg><span class="post-nav-text">生产实习</span></a></div><div class="post-nav-item"></div></div></div><div id="comment"><div class="comment-tooltip text-center"><span>点击按钮跳转 GitHub Issues 评论</span><br><span>若没有本文 Issue，您可以使用 Comment 模版新建</span><br><a class="hty-button hty-button--raised" id="github-issues" target="_blank" rel="noopener" href="https://github.com/ccknbc-backup/comments/issues?q=is:issue+基于小波变换的数字水印检测">GitHub Issues</a></div><div id="disqus_thread"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/disqusjs@latest/dist/disqusjs.css"><script src="https://cdn.jsdelivr.net/npm/disqusjs@latest/dist/disqus.js"></script><script>const disqusjsConfig = {"enable":true,"shortname":"ccknbc","count":true,"apikey":"Z6F8Gc9KvW2YCh6p11VRVNvMBYfdaKR3IMRFLVmoYaIQJ2ysp38fZ9tivPdgyBWu","siteName":"CC的部落格","identifier":null,"url":null,"title":null,"nesting":4,"nocomment":"这里冷冷清清的，一条评论也没有，快来留下脚印吧！","admin":"ccknbc","adminLabel":"ccknbc"}
function loadDisqus() {
  const dsqjs = new DisqusJS(disqusjsConfig)
}</script><script src="/yun/js/comments/disqus.js"></script><style>.utterances {
  max-width: 100%;
}</style><script src="https://utteranc.es/client.js" repo="ccknbc-backup/comments" issue-term="title" label="💬comment" theme="github-light" crossorigin="anonymous" async></script></div></main><footer class="sidebar-translate" id="footer"><div class="copyright"><span>&copy; 2020 </span><span class="with-love" id="animate"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-cloud-line"></use></svg></span><span class="author"> CC康纳百川</span></div><div class="powered"><span>由 <a href="https://hexo.io" target="_blank" rel="noopener">Hexo</a> 驱动 v5.2.0</span><span class="footer-separator">|</span><span>主题 - <a rel="noopener" href="https://github.com/YunYouJun/hexo-theme-yun" target="_blank"><span>Yun</span></a> v1.2.0</span></div><div class="live_time"><span>本博客已萌萌哒地运行</span><span id="display_live_time"></span><span class="moe-text">(●'◡'●)</span><script>function blog_live_time() {
  window.setTimeout(blog_live_time, 1000);
  const start = new Date('2020-06-04T00:00:00');
  const now = new Date();
  const timeDiff = (now.getTime() - start.getTime());
  const msPerMinute = 60 * 1000;
  const msPerHour = 60 * msPerMinute;
  const msPerDay = 24 * msPerHour;
  const passDay = Math.floor(timeDiff / msPerDay);
  const passHour = Math.floor((timeDiff % msPerDay) / 60 / 60 / 1000);
  const passMinute = Math.floor((timeDiff % msPerHour) / 60 / 1000);
  const passSecond = Math.floor((timeDiff % msPerMinute) / 1000);
  display_live_time.innerHTML = " " + passDay + " 天 " + passHour + " 小时 " + passMinute + " 分 " + passSecond + " 秒";
}
blog_live_time();
</script></div><div id="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_site_uv" title="总访客量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-user-line"></use></svg></span><span id="busuanzi_value_site_uv"></span></span><span class="footer-separator">|</span><span id="busuanzi_container_site_pv" title="总访问量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg></span><span id="busuanzi_value_site_pv"></span></span></div></footer><a class="hty-icon-button" id="goUp" aria-label="back-to-top" href="#"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-up-s-line"></use></svg><svg class="progress-circle-container" viewBox="0 0 100 100"><circle class="progress-circle" id="progressCircle" cx="50" cy="50" r="48" fill="none" stroke="#0078E7" stroke-width="2" stroke-linecap="round"></circle></svg></a><a class="popup-trigger hty-icon-button icon-search" id="search" href="javascript:;" title="搜索"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search-line"></use></svg></span></a><script>window.addEventListener("DOMContentLoaded", () => {
  // Handle and trigger popup window
  document.querySelector(".popup-trigger").addEventListener("click", () => {
    document.querySelector(".popup").classList.add("show");
    setTimeout(() => {
      document.querySelector(".search-input").focus();
    }, 100);
  });

  // Monitor main search box
  const onPopupClose = () => {
    document.querySelector(".popup").classList.remove("show");
  };

  document.querySelector(".popup-btn-close").addEventListener("click", () => {
    onPopupClose();
  });

  window.addEventListener("keyup", event => {
    if (event.key === "Escape") {
      onPopupClose();
    }
  });
});
</script><script src="/yun/js/search/local-search.js" defer></script><div class="popup search-popup"><div class="search-header"><span class="popup-btn-close close-icon hty-icon-button"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-close-line"></use></svg></span></div><div class="search-input-container"><input class="search-input" id="local-search-input" type="text" placeholder="搜索..." value=""></div><div id="local-search-result"></div></div><script>const date = new Date();
const today = (date.getMonth() + 1) + "-" + date.getDate()
const mourn_days = ["4-4","9-18"]
if (mourn_days.includes(today)) {
  document.documentElement.style.filter = "grayscale(1)";
}</script></div><script defer src="/yun/js/utils.js"></script><script defer src="/yun/js/hexo-theme-yun.js"></script></body></html>